条件分岐するRISC-Vコードを出力 (sum.ml)
https://gyazo.com/c41a9d53d6907a669c2e4994ee40196f
条件分岐を含む以下のような簡単なコード(sum.ml)が動くようになった。
code:sum.ml
let rec sum x =
if x <= 0 then 0 else
sum (x - 1) + x in
print_int (sum 10000)
変更箇所は以下のとおり。
stw → sw
lwz → lw
subi → addi(負の値をaddするようにした)
blr → ret
mr → mv
Tail, IfLE(x, C(y), e1, e2) で ble を使って条件分岐するようにした
他の条件分岐のコードの修正も必要だが、必要になってから直す予定
code:diff
diff --git a/RV32/emit.ml b/RV32/emit.ml
index 0223256..71477aa 100644
--- a/RV32/emit.ml
+++ b/RV32/emit.ml
@@ -78,7 +78,7 @@ and g' oc = function (* 各命令のアセンブリ生成 (caml2html: emit_gprim
| NonTail(x), Add(y, V(z)) -> Printf.fprintf oc "\tadd\t%s, %s, %s\n" (reg x) (reg y) (reg z)
| NonTail(x), Add(y, C(z)) -> Printf.fprintf oc "\taddi\t%s, %s, %d\n" (reg x) (reg y) z
| NonTail(x), Sub(y, V(z)) -> Printf.fprintf oc "\tsub\t%s, %s, %s\n" (reg x) (reg y) (reg z)
- | NonTail(x), Sub(y, C(z)) -> Printf.fprintf oc "\tsubi\t%s, %s, %d\n" (reg x) (reg y) z
+ | NonTail(x), Sub(y, C(z)) -> Printf.fprintf oc "\taddi %s, %s, %d\n" (reg x) (reg y) ((-1) * z)
| NonTail(x), Slw(y, V(z)) -> Printf.fprintf oc "\tslw\t%s, %s, %s\n" (reg x) (reg y) (reg z)
| NonTail(x), Slw(y, C(z)) -> Printf.fprintf oc "\tslwi\t%s, %s, %d\n" (reg x) (reg y) z
| NonTail(x), Lwz(y, V(z)) -> Printf.fprintf oc "\tlwzx\t%s, %s, %s\n" (reg x) (reg y) (reg z)
@@ -100,80 +100,81 @@ and g' oc = function (* 各命令のアセンブリ生成 (caml2html: emit_gprim
(* 退避の仮想命令の実装 (caml2html: emit_save) *)
| NonTail(_), Save(x, y) when List.mem x allregs && not (S.mem y !stackset) ->
save y;
- Printf.fprintf oc "\tstw\t%s, %d(%s)\n" (reg x) (offset y) (reg reg_sp)
+ Printf.fprintf oc "\tsw %s, %d(%s)\n" (reg x) (offset y) (reg reg_sp)
| NonTail(_), Save(x, y) when List.mem x allfregs && not (S.mem y !stackset) ->
savef y;
Printf.fprintf oc "\tstfd\t%s, %d(%s)\n" (reg x) (offset y) (reg reg_sp)
| NonTail(_), Save(x, y) -> assert (S.mem y !stackset); ()
(* 復帰の仮想命令の実装 (caml2html: emit_restore) *)
| NonTail(x), Restore(y) when List.mem x allregs ->
- Printf.fprintf oc "\tlwz\t%s, %d(%s)\n" (reg x) (offset y) (reg reg_sp)
+ Printf.fprintf oc "\tlw %s, %d(%s)\n" (reg x) (offset y) (reg reg_sp)
| NonTail(x), Restore(y) ->
assert (List.mem x allfregs);
Printf.fprintf oc "\tlfd\t%s, %d(%s)\n" (reg x) (offset y) (reg reg_sp)
(* 末尾だったら計算結果を第一レジスタにセットしてリターン (caml2html: emit_tailret) *)
| Tail, (Nop | Stw _ | Stfd _ | Comment _ | Save _ as exp) ->
g' oc (NonTail(Id.gentmp Type.Unit), exp);
- Printf.fprintf oc "\tblr\n";
+ Printf.fprintf oc "\tret\n";
| Tail, (Li _ | SetL _ | Mr _ | Neg _ | Add _ | Sub _ | Slw _ | Lwz _ as exp) ->
g' oc (NonTail(regs.(0)), exp);
- Printf.fprintf oc "\tblr\n";
+ Printf.fprintf oc "\tret\n";
| Tail, (FLi _ | FMr _ | FNeg _ | FAdd _ | FSub _ | FMul _ | FDiv _ | Lfd _ as exp) ->
g' oc (NonTail(fregs.(0)), exp);
- Printf.fprintf oc "\tblr\n";
+ Printf.fprintf oc "\tret\n";
| Tail, (Restore(x) as exp) ->
(match locate x with
| i -> g' oc (NonTail(regs.(0)), exp) | i; j when i + 1 = j -> g' oc (NonTail(fregs.(0)), exp) | _ -> assert false);
- Printf.fprintf oc "\tblr\n";
+ Printf.fprintf oc "\tret\n";
| Tail, IfEq(x, V(y), e1, e2) ->
- Printf.fprintf oc "\tcmpw\tcr7, %s, %s\n" (reg x) (reg y);
+ Printf.fprintf oc "\tcmpw\tcr7@, %s, %s\n" (reg x) (reg y);
g'_tail_if oc e1 e2 "beq" "bne"
| Tail, IfEq(x, C(y), e1, e2) ->
- Printf.fprintf oc "\tcmpwi\tcr7, %s, %d\n" (reg x) y;
+ Printf.fprintf oc "\tcmpwi\tcr7@, %s, %d\n" (reg x) y;
g'_tail_if oc e1 e2 "beq" "bne"
| Tail, IfLE(x, V(y), e1, e2) ->
- Printf.fprintf oc "\tcmpw\tcr7, %s, %s\n" (reg x) (reg y);
+ Printf.fprintf oc "\tcmpw\tcr7@, %s, %s\n" (reg x) (reg y);
g'_tail_if oc e1 e2 "ble" "bgt"
| Tail, IfLE(x, C(y), e1, e2) ->
- Printf.fprintf oc "\tcmpwi\tcr7, %s, %d\n" (reg x) y;
- g'_tail_if oc e1 e2 "ble" "bgt"
+ (* 新しい if 実装済み *)
+ Printf.fprintf oc "\tli %s, %d\n" (reg reg_tmp) y;
+ g'_tail_if_new oc (reg x) (reg reg_tmp) e1 e2 "ble" "bgt"
| Tail, IfGE(x, V(y), e1, e2) ->
- Printf.fprintf oc "\tcmpw\tcr7, %s, %s\n" (reg x) (reg y);
+ Printf.fprintf oc "\tcmpw\tcr7@, %s, %s\n" (reg x) (reg y);
g'_tail_if oc e1 e2 "bge" "blt"
| Tail, IfGE(x, C(y), e1, e2) ->
- Printf.fprintf oc "\tcmpwi\tcr7, %s, %d\n" (reg x) y;
+ Printf.fprintf oc "\tcmpwi\tcr7@, %s, %d\n" (reg x) y;
g'_tail_if oc e1 e2 "bge" "blt"
| Tail, IfFEq(x, y, e1, e2) ->
- Printf.fprintf oc "\tfcmpu\tcr7, %s, %s\n" (reg x) (reg y);
+ Printf.fprintf oc "\tfcmpu\tcr7@, %s, %s\n" (reg x) (reg y);
g'_tail_if oc e1 e2 "beq" "bne"
| Tail, IfFLE(x, y, e1, e2) ->
- Printf.fprintf oc "\tfcmpu\tcr7, %s, %s\n" (reg x) (reg y);
+ Printf.fprintf oc "\tfcmpu\tcr7@, %s, %s\n" (reg x) (reg y);
g'_tail_if oc e1 e2 "ble" "bgt"
| NonTail(z), IfEq(x, V(y), e1, e2) ->
- Printf.fprintf oc "\tcmpw\tcr7, %s, %s\n" (reg x) (reg y);
+ Printf.fprintf oc "\tcmpw\tcr7@@, %s, %s\n" (reg x) (reg y);
g'_non_tail_if oc (NonTail(z)) e1 e2 "beq" "bne"
| NonTail(z), IfEq(x, C(y), e1, e2) ->
- Printf.fprintf oc "\tcmpwi\tcr7, %s, %d\n" (reg x) y;
+ Printf.fprintf oc "\tcmpwi\tcr7@@, %s, %d\n" (reg x) y;
g'_non_tail_if oc (NonTail(z)) e1 e2 "beq" "bne"
| NonTail(z), IfLE(x, V(y), e1, e2) ->
- Printf.fprintf oc "\tcmpw\tcr7, %s, %s\n" (reg x) (reg y);
+ Printf.fprintf oc "\tcmpw\tcr7@@, %s, %s\n" (reg x) (reg y);
g'_non_tail_if oc (NonTail(z)) e1 e2 "ble" "bgt"
| NonTail(z), IfLE(x, C(y), e1, e2) ->
- Printf.fprintf oc "\tcmpwi\tcr7, %s, %d\n" (reg x) y;
+ Printf.fprintf oc "\tcmpwi\tcr7@@, %s, %d\n" (reg x) y;
g'_non_tail_if oc (NonTail(z)) e1 e2 "ble" "bgt"
| NonTail(z), IfGE(x, V(y), e1, e2) ->
- Printf.fprintf oc "\tcmpw\tcr7, %s, %s\n" (reg x) (reg y);
+ Printf.fprintf oc "\tcmpw\tcr7@@, %s, %s\n" (reg x) (reg y);
g'_non_tail_if oc (NonTail(z)) e1 e2 "bge" "blt"
| NonTail(z), IfGE(x, C(y), e1, e2) ->
- Printf.fprintf oc "\tcmpwi\tcr7, %s, %d\n" (reg x) y;
+ Printf.fprintf oc "\tcmpwi\tcr7@@, %s, %d\n" (reg x) y;
g'_non_tail_if oc (NonTail(z)) e1 e2 "bge" "blt"
| NonTail(z), IfFEq(x, y, e1, e2) ->
- Printf.fprintf oc "\tfcmpu\tcr7, %s, %s\n" (reg x) (reg y);
+ Printf.fprintf oc "\tfcmpu\tcr7@@, %s, %s\n" (reg x) (reg y);
g'_non_tail_if oc (NonTail(z)) e1 e2 "beq" "bne"
| NonTail(z), IfFLE(x, y, e1, e2) ->
- Printf.fprintf oc "\tfcmpu\tcr7, %s, %s\n" (reg x) (reg y);
+ Printf.fprintf oc "\tfcmpu\tcr7@@, %s, %s\n" (reg x) (reg y);
g'_non_tail_if oc (NonTail(z)) e1 e2 "ble" "bgt"
(* 関数呼び出しの仮想命令の実装 (caml2html: emit_call) *)
| Tail, CallCls(x, ys, zs) -> (* 末尾呼び出し (caml2html: emit_tailcall) *)
@@ -219,9 +220,19 @@ and g' oc = function (* 各命令のアセンブリ生成 (caml2html: emit_gprim
(* tmp レジスタから ra を復帰 *)
Printf.fprintf oc "\tmv ra, %s\n" (reg reg_tmp)
+and g'_tail_if_new oc x y e1 e2 b bn =
+ (* 新しい g'_tail_if *)
+ let b_else = Id.genid (b ^ "_else") in
+ Printf.fprintf oc "\t%s %s, %s, %s\n" bn x y b_else;
+ let stackset_back = !stackset in
+ g oc (Tail, e1);
+ Printf.fprintf oc "%s:\n" b_else;
+ stackset := stackset_back;
+ g oc (Tail, e2)
and g'_tail_if oc e1 e2 b bn =
+ (* いずれ消す古い g'_tail_if *)
let b_else = Id.genid (b ^ "_else") in
- Printf.fprintf oc "\t%s\tcr7, %s\n" bn b_else;
+ Printf.fprintf oc "\t%s\tcr7@, %s\n" bn b_else;
let stackset_back = !stackset in
g oc (Tail, e1);
Printf.fprintf oc "%s:\n" b_else;
@@ -230,7 +241,7 @@ and g'_tail_if oc e1 e2 b bn =
and g'_non_tail_if oc dest e1 e2 b bn =
let b_else = Id.genid (b ^ "_else") in
let b_cont = Id.genid (b ^ "_cont") in
- Printf.fprintf oc "\t%s\tcr7, %s\n" bn b_else;
+ Printf.fprintf oc "\t%s\tcr7@@, %s\n" bn b_else;
let stackset_back = !stackset in
g oc (dest, e1);
let stackset1 = !stackset in
@@ -248,7 +259,7 @@ and g'_args oc x_reg_cl ys zs =
(0, x_reg_cl)
ys in
List.iter
- (fun (y, r) -> Printf.fprintf oc "\tmr\t%s, %s\n" (reg r) (reg y))
+ (fun (y, r) -> Printf.fprintf oc "\tmv %s, %s\n" (reg r) (reg y))
(shuffle reg_sw yrs);
let (d, zfrs) =
List.fold_left
参考